package com.generator.demo.utils.generatorUtil;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Map;

@Slf4j
public class FreemarkerUtils {

    //表前缀名称,首字母写出大写,作为mybatisPlus生成文件的前缀名
    private final static String TABLE_PREFIX = "Ln";
    //项目根路径,如果是多模块则在后面加入模块名：+"/模块名"
    private final static String PATH = System.getProperty("user.dir");
    //java路径
    private final static String JAVA_PATH = "/src/main/java";
    //总包的路径
    private final static String PACKAGE = "/com/generator/demo";
    //dto的包路径
    private final static String DTO_PACKAGE = "/model/dto";
    //vo的包路径
    private final static String VO_PACKAGE = "/model/vo";
    //service的包路径
    private final static String SERVICE_PACKAGE = "/service";
    //impl的包路径
    private final static String IMPL_PACKAGE = "/service/impl";
    //controller的包路径
    private final static String CONTROLLER_PACKAGE = "/controller";
    //mybatisPlus的Service的包路径
    private final static String TB_SERVICE_PACKAGE = "/ln/service";
    //mybatisPlus的Mapper的包路径
    private final static String TB_MAPPER_PACKAGE = "/ln/mapper";
    //mybatisPlus的entity的包路径
    private final static String TB_ENTITY_PACKAGE = "/ln/entity";

    //工具类的包路径
    //CommonResult的包路径
    private final static String COMMON_RESULT_PACKAGE = "/common/api";
    //PageQuery的包路径
    private final static String PAGE_QUERY_PACKAGE = "/common/pageHelp";
    //PageVo的包路径
    private final static String PAGE_VO_PACKAGE = "/common/pageHelp";
    //EmptyUtil的包路径
    private final static String EMPTY_UTIL_PACKAGE = "/utils";
    //BeanUtil的包路径
    private final static String BEAN_UTIL_PACKAGE = "/utils";

    //java文件后缀名,程序中会在前面拼接表名称
    //addDto
    private final static String ADD_DTO_JAVA = "AddDto";
    //changeDto
    private final static String CHANGE_DTO_JAVA = "ChangeDto";
    //listDto
    private final static String LIST_DTO_JAVA = "ListDto";
    //pageDto
    private final static String PAGE_DTO_JAVA = "PageDto";
    //removeDto
    private final static String REMOVE_DTO_JAVA = "RemoveDto";
    //Vo
    private final static String VO_JAVA = "Vo";
    //serviceDto
    private final static String SERVICE_JAVA = "Service";
    //implDto
    private final static String IMPL_JAVA = "ServiceImpl";
    //mapper
    private final static String MAPPER_JAVA = "Mapper";
    //controller
    private final static String CONTROLLER_JAVA = "Controller";

    static {

        /** 生成dto文件目录 */
        String dtoPath = PATH + JAVA_PATH + PACKAGE + DTO_PACKAGE;
        createFolder(dtoPath);
        /** 生成vo文件目录 */
        String voPath = PATH + JAVA_PATH + PACKAGE + VO_PACKAGE;
        createFolder(voPath);
        /** 生成service文件目录 */
        String servicePath = PATH + JAVA_PATH + PACKAGE + SERVICE_PACKAGE;
        createFolder(servicePath);
        /** 生成impl文件目录 */
        String implPath = PATH + JAVA_PATH + PACKAGE + IMPL_PACKAGE;
        createFolder(implPath);
        /** 生成controller文件目录 */
        String controllerPath = PATH + JAVA_PATH + PACKAGE + CONTROLLER_PACKAGE;
        createFolder(controllerPath);

    }

    public static void createFolder(String path) {
        File file = new File(path);
        createParentPath(file);
        if (!file.exists()) {
            file.mkdir();
        }
    }

    public static void createParentPath(File file) {
        File parentFile = file.getParentFile();
        if (null != parentFile && !parentFile.exists()) {
            //创建文件夹
            parentFile.mkdirs();
            // 递归创建父级目录
            createParentPath(parentFile);
        }
    }

    /**
     * 需要生成代码的表数组
     *
     * @param tables
     * @throws Exception
     */
    public static void createFtl(String... tables) {
        for (String string : tables) {
            String tableName = string;
            //获取表字段信息
            Map<String, Object> map = DBHelper.getTableInfo(tableName);
            String clsName = map.get("clsName").toString().substring(2);
            //把数据库表名去掉两位前缀
            map.put("clsName", clsName);

            //设置mybatisPlus生成文件的前缀名
            map.put("tablePrefix", TABLE_PREFIX);

            //设置包路径
            map.put("voPackage", (PACKAGE + VO_PACKAGE).substring(1).replace('/', '.'));
            map.put("dtoPackage", (PACKAGE + DTO_PACKAGE).substring(1).replace('/', '.'));
            map.put("servicePackage", (PACKAGE + SERVICE_PACKAGE).substring(1).replace('/', '.'));
            map.put("implPackage", (PACKAGE + IMPL_PACKAGE).substring(1).replace('/', '.'));
            map.put("controllerPackage", (PACKAGE + CONTROLLER_PACKAGE).substring(1).replace('/', '.'));

            //设置tb包路径
            map.put("tbEntityPackage", (PACKAGE + TB_ENTITY_PACKAGE).substring(1).replace('/', '.'));
            map.put("tbMapperPackage", (PACKAGE + TB_MAPPER_PACKAGE).substring(1).replace('/', '.'));
            map.put("tbServicePackage", (PACKAGE + TB_SERVICE_PACKAGE).substring(1).replace('/', '.'));

            //设置Java文件名称
            map.put("voName", clsName + VO_JAVA);
            map.put("addDtoName", clsName + ADD_DTO_JAVA);
            map.put("changeDtoName", clsName + CHANGE_DTO_JAVA);
            map.put("listDtoName", clsName + LIST_DTO_JAVA);
            map.put("pageDtoName", clsName + PAGE_DTO_JAVA);
            map.put("removeDtoName", clsName + REMOVE_DTO_JAVA);
            map.put("serviceName", clsName + SERVICE_JAVA);
            map.put("implName", clsName + IMPL_JAVA);
            map.put("mapperName", clsName + MAPPER_JAVA);
            map.put("controllerName", clsName + CONTROLLER_JAVA);

            //设置Java文件路径
            map.put("voJava", (PACKAGE + VO_PACKAGE).substring(1).replace('/', '.') + "." + clsName + VO_JAVA);
            map.put("addDtoJava", (PACKAGE + DTO_PACKAGE).substring(1).replace('/', '.') + "." + clsName + ADD_DTO_JAVA);
            map.put("changeDtoJava", (PACKAGE + DTO_PACKAGE).substring(1).replace('/', '.') + "." + clsName + CHANGE_DTO_JAVA);
            map.put("listDtoJava", (PACKAGE + DTO_PACKAGE).substring(1).replace('/', '.') + "." + clsName + LIST_DTO_JAVA);
            map.put("pageDtoJava", (PACKAGE + DTO_PACKAGE).substring(1).replace('/', '.') + "." + clsName + PAGE_DTO_JAVA);
            map.put("removeDtoJava", (PACKAGE + DTO_PACKAGE).substring(1).replace('/', '.') + "." + clsName + REMOVE_DTO_JAVA);
            map.put("serviceJava", (PACKAGE + SERVICE_PACKAGE).substring(1).replace('/', '.') + "." + clsName + SERVICE_JAVA);
            map.put("implJava", (PACKAGE + IMPL_PACKAGE).substring(1).replace('/', '.') + "." + clsName + IMPL_JAVA);

            map.put("commonResultJava", (PACKAGE + COMMON_RESULT_PACKAGE).substring(1).replace('/', '.') + ".CommonResult");
            map.put("pageQueryJava", (PACKAGE + PAGE_QUERY_PACKAGE).substring(1).replace('/', '.') + ".PageQuery");
            map.put("pageVoJava", (PACKAGE + PAGE_VO_PACKAGE).substring(1).replace('/', '.') + ".PageVo");
            map.put("emptyUtilJava", (PACKAGE + EMPTY_UTIL_PACKAGE).substring(1).replace('/', '.') + ".EmptyUtil");
            map.put("beanUtilJava", (PACKAGE + BEAN_UTIL_PACKAGE).substring(1).replace('/', '.') + ".BeanUtil");

            //生成的文件名
            String voFile = PATH + JAVA_PATH + PACKAGE + VO_PACKAGE + "/" + clsName + VO_JAVA + ".java";
            String addDtoFile = PATH + JAVA_PATH + PACKAGE + DTO_PACKAGE + "/" + clsName + ADD_DTO_JAVA + ".java";
            String changeDtoFile = PATH + JAVA_PATH + PACKAGE + DTO_PACKAGE + "/" + clsName + CHANGE_DTO_JAVA + ".java";
            String removeDtoFile = PATH + JAVA_PATH + PACKAGE + DTO_PACKAGE + "/" + clsName + REMOVE_DTO_JAVA + ".java";
            String listDtoFile = PATH + JAVA_PATH + PACKAGE + DTO_PACKAGE + "/" + clsName + LIST_DTO_JAVA + ".java";
            String pageDtoFile = PATH + JAVA_PATH + PACKAGE + DTO_PACKAGE + "/" + clsName + PAGE_DTO_JAVA + ".java";
            String serviceFile = PATH + JAVA_PATH + PACKAGE + SERVICE_PACKAGE + "/" + clsName + SERVICE_JAVA + ".java";
            String serviceImplFile = PATH + JAVA_PATH + PACKAGE + IMPL_PACKAGE + "/" + clsName + IMPL_JAVA + ".java";
            String controllerFile = PATH + JAVA_PATH + PACKAGE + CONTROLLER_PACKAGE + "/" + clsName + CONTROLLER_JAVA + ".java";
            try {
                if (!fileExist(voFile)) {
                    log.info("********创建vo文件********");
                    // 生成vo
                    createFile("vo.java.ftl", voFile, map);
                }
                if (!fileExist(addDtoFile)) {
                    log.info("********创建addDto文件********");
                    // 生成添加dto
                    createFile("addDto.java.ftl", addDtoFile, map);
                }
                if (!fileExist(changeDtoFile)) {
                    log.info("********创建changeDto文件********");
                    // 生成修改dto
                    createFile("changeDto.java.ftl", changeDtoFile, map);
                }
                if (!fileExist(removeDtoFile)) {
                    log.info("********创建removeDto文件********");
                    // 生成删除dto
                    createFile("removeDto.java.ftl", removeDtoFile, map);
                }
                if (!fileExist(listDtoFile)) {
                    log.info("********创建listDto文件********");
                    // 生成dto
                    createFile("listDto.java.ftl", listDtoFile, map);
                }
                if (!fileExist(pageDtoFile)) {
                    log.info("********创建pageDto文件********");
                    // 生成分页查询dto
                    createFile("pageDto.java.ftl", pageDtoFile, map);
                }
                if (!fileExist(serviceFile)) {
                    log.info("********创建service文件********");
                    // 生成service
                    createFile("service.java.ftl", serviceFile, map);
                }
                if (!fileExist(serviceImplFile)) {
                    log.info("********创建impl文件********");
                    // 生成impl
                    createFile("serviceImpl.java.ftl", serviceImplFile, map);
                }
                if (!fileExist(controllerFile)) {
                    log.info("********创建controller文件********");
                    // 生成controller
                    createFile("controller.java.ftl", controllerFile, map);
                }
                log.info("文件创建完成");
            } catch (Exception e) {
                log.info("文件创建异常：{}", e.getMessage());
            }
        }
    }

    /**
     * 设置ftl模板的路径
     *
     * @param templatName
     * @param fileName
     * @param map
     * @throws IOException
     * @throws TemplateException
     */
    public static void createFile(String templatName, String fileName, Map<String, Object> map) throws IOException, TemplateException {
        @SuppressWarnings("deprecation")
        Configuration cfg = new Configuration();
        //！！！注意模板的路径"templates/mvc"
        String path = FreemarkerUtils.class.getResource("/").getPath() + "templates/mvc";
        cfg.setDirectoryForTemplateLoading(new File(path));
        Template t = cfg.getTemplate(templatName);
        t.process(map, new OutputStreamWriter(new FileOutputStream(fileName)));
    }

    /**
     * 判断文件是否存在
     *
     * @param path
     * @return
     */
    public static Boolean fileExist(String path) {
        Boolean flag = false;
        File file = new File(path);
        if (file.exists()) {
            flag = true;
        }
        return flag;
    }

    public static void main(String[] args) {
        createFtl("tb_contract");
    }
}
